package com.atguigu.exam.service.impl;


import com.atguigu.exam.entity.Category;
import com.atguigu.exam.entity.Question;
import com.atguigu.exam.exception.ExamException;
import com.atguigu.exam.mapper.CategoryMapper;
import com.atguigu.exam.mapper.QuestionMapper;
import com.atguigu.exam.service.CategoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
    @Autowired
    private QuestionMapper questionMapper;



    @Override
    public List<Category> getCategoresList() {
        //获取所有的分类，单表查，直接调mybatis plus中的方法，根据sort升序查询所有题目的分类列表封装到list集合中，
//      List<Category> selectList = baseMapper.selectList(new LambdaQueryWrapper<Category>().orderByAsc(Category::getSort));
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<Category> categories = baseMapper.selectList(categoryLambdaQueryWrapper.orderByAsc(Category::getSort));
        //试题类型集合
//      计算子分类数量并添加
        addCount(categories);
        return categories;
    }

    private void addCount(List<Category> categories) {
        //      拿到分类列表后根据前端需求，再把属于各分类的题目的数量设置上去，此时需要查question表中的数据，统计每个类型题目有几道题
//      把题目类型作为K值，题目数量作为V值，整合到形成map集合，全部map形成list集合  需要装配question的mapper映射
//      getCategoryCount需要到mapper中写方法的接口，然后到mapper.xml文件中写具体的查询语句
        List<Map<Long,Long>> categoryCount = questionMapper.getCategoryCount();
        //出现的试题类型和对应的数量

//      把查询出的结果 取了别名（count）设置给categories表中的count列 遍历list集合中的map集合，取出count设置或使用流处理
//      把list集合使用stream流转换为Map集合  得到一个map集合   k和v值通过get获取，赋给map中的键值对
        Map<Long, Long> categoryIDmap = categoryCount.stream().collect(Collectors.toMap(
                k -> k.get("category_id"),
                v -> v.get("count")
        ));
        //拿到数量set给试题类型集合categories中的count值
        categories.forEach(category ->{
            //根据id值获取对应的数量，如果只有题目类型，没有题目，则设为默认值0，即当前类没有题
            Long count = categoryIDmap.getOrDefault(category.getId(), 0L);
            category.setCount(count);
        });
    }

    @Override
    public List<Category> getCategoryTree() {
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<Category> categories = baseMapper.selectList(categoryLambdaQueryWrapper.orderByAsc(Category::getSort));
//      只增加了子分类的数量
        addCount(categories);
//      构建分类树
        List<Category> parentCategoryList = buildCategoryTree(categories);
        return parentCategoryList;
    }



    private List<Category> buildCategoryTree(List<Category> categories) {
        //      将categories中的数据根据parent_id 用stream流分组  再把 对应的题设置给它们  完成树结构
        Map<Long, List<Category>> categorymap= categories.stream().collect(Collectors.groupingBy(Category::getParentId));
//      long  即parent id 为k   v 是它的子题目  是一个list集合
//      遍历所有分类，拿到试题类型的id
        categories.forEach(category -> {
            Long categoryId = category.getId();
            //获取子分类的列表
            List<Category> childrenCategory = categorymap.getOrDefault(categoryId, new ArrayList<>());

//          把得到的孩子设置给当前分类
            category.setChildren(childrenCategory);

//          获取所有子分类数量之和
            long childrenCount = childrenCategory.stream().mapToLong(Category::getCount).sum();
//          获取一级列表的题目数量
            Long parentCount = category.getCount();

            //重新设置总数量
            category.setCount(childrenCount+parentCount);
        });
//      获取一级题目
        List<Category> parentCategoryList = categories.stream().filter(category -> category.getParentId() == 0).collect(Collectors.toList());

        return parentCategoryList;
    }

    @Override
    public void addCategory(Category category) {
//      根据name 和parent id 两个条件判断创建的题目类型是否存在

        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();

        categoryLambdaQueryWrapper.eq(Category::getName,category.getName()).eq(Category::getParentId,category.getParentId());

        boolean exists = baseMapper.exists(categoryLambdaQueryWrapper);
        if (exists){
            String name = baseMapper.selectById(category.getParentId()).getName();
            throw new ExamException(412,name + "中已存在" + category.getName() + "!");
        }
        baseMapper.insert(category);
    }

    @Override
    public void updateCategory(Category category) {
//        根据name 和parent id 两个条件判断创建的题目类型是否存在
//      存在时   当id等于自己id时，可以更新自己，当id不等于自己的id就不能更新成其他子题目
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        boolean exists = baseMapper.exists(categoryLambdaQueryWrapper.eq(Category::getName, category.getName()).eq(Category::getParentId, category.getParentId()).ne(Category::getId, category.getId()));
        if (exists){
            String name = baseMapper.selectById(category.getParentId()).getName();
            throw new ExamException(422,name + "中已存在" + category.getName() + "!");
        }
        baseMapper.updateById(category);

    }

    @Override
    public void deleteById(Long id) {
//      判断parent id 是不是等于当前一级分类的id 如果等于，代表有子分类，则不能删
        Long count = baseMapper.selectCount(new LambdaQueryWrapper<Category>().eq(Category::getParentId, id));
        if (count > 0){
//      代表有子分类
            throw new ExamException(455,"当前题型存在子题型，请检查后再删除！");
        }
//        判断子分类下有没有题  看question表
        Long count1 = questionMapper.selectCount(new LambdaQueryWrapper<Question>().eq(Question::getCategoryId, id));
        if (count1 > 0){
//      代表有子分类下有题目
            throw new ExamException(555,"当前题型下存在题目，请检查后再删除！");
        }
        baseMapper.deleteById(id);
    }


}